package cn.wecloud.im.multiplayervideodemo.act

import android.Manifest
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import cn.wecloud.im.core.http.model.RTCChannel
import cn.wecloud.im.core.im.IMClient
import cn.wecloud.im.core.im.IMConversation
import cn.wecloud.im.core.im.IMMessageManager
import cn.wecloud.im.core.im.IMRTCHandler
import cn.wecloud.im.core.im.callback.ICallback
import cn.wecloud.im.core.im.messages.Command
import cn.wecloud.im.core.im.messages.RTCEvent
import cn.wecloud.im.exception.WeException
import cn.wecloud.im.multiplayervideodemo.R
import cn.wecloud.im.multiplayervideodemo.ext.show
import cn.wecloud.im.multiplayervideodemo.fragment.VideoAnswerFragment
import cn.wecloud.im.multiplayervideodemo.fragment.VideoCallFragment
import cn.wecloud.im.multiplayervideodemo.fragment.VideoControlFragment
import cn.wecloud.im.multiplayervideodemo.rtc.VideoChatHelper
import cn.wecloud.im.multiplayervideodemo.utils.AppSharePre
import cn.wecloud.im.multiplayervideodemo.utils.DateFormatHelper
import cn.wecloud.im.multiplayervideodemo.utils.SoundPlayUtils
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.tbruyelle.rxpermissions2.RxPermissions
import kotlinx.android.synthetic.main.activity_video.*
import org.webrtc.EglBase
import org.webrtc.IceCandidate
import org.webrtc.RendererCommon
import org.webrtc.SessionDescription

class VideoActivity : AppCompatActivity() {

    companion object {
        private const val TAG = "VideoActivity"
        const val TO_CLIENT = "toClient"
        const val RTC_TYPE = "rtcType"
        const val CONVERSATION_ID = "conversationId"
        const val CALLER = "caller"
        const val CHANNEL_ID = "channelId"


        fun startCall(
            content: Context,
            toClient: String,
            rtcType: Command.WeRtcType,
            conversationId: Long
        ) {
            val intent = Intent(
                content,
                VideoActivity::class.java
            ).putExtra(TO_CLIENT, toClient)
                .putExtra(RTC_TYPE, rtcType.code)
                .putExtra(CONVERSATION_ID, conversationId)
                .putExtra(CALLER, true)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

            content.startActivity(intent)
        }

        fun startAnswer(
            content: Context,
            channelId: Long,
            toClient: String,
            rtcType: Int,
            conversationId: Long
        ) {
            val intent = Intent(
                content,
                VideoActivity::class.java
            ).putExtra(TO_CLIENT, toClient)
                .putExtra(RTC_TYPE, rtcType)
                .putExtra(CONVERSATION_ID, conversationId)
                .putExtra(CALLER, false)
                .putExtra(CHANNEL_ID, channelId)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            content.startActivity(intent)
        }
    }

    private val toClient: String by lazy {
        intent.getStringExtra(TO_CLIENT) ?: ""
    }
    private val rtcType: Command.WeRtcType by lazy {
        val code = intent.getIntExtra(RTC_TYPE, 0)
        Command.WeRtcType.getType(code)
    }
    private val conversationId: Long by lazy {
        intent.getLongExtra(CONVERSATION_ID, 0L)
    }
    private val isCaller: Boolean by lazy {
        intent.getBooleanExtra(CALLER, true)
    }
    private val rxPermission: RxPermissions by lazy {
        RxPermissions(this)
    }
    private var channelId: Long = 0L

    /**
     * 音视频Helper
     */
    private var videoChatHelper: VideoChatHelper? = null
        get() {
            if (field == null) {
                field =
                    VideoChatHelper(this@VideoActivity, rtcType.code, rootEglBase?.eglBaseContext)
            }
            return field
        }

    private val videoCallFragment: VideoCallFragment by lazy {
        VideoCallFragment.newInstance(toClient, rtcType.code).apply {
            supportFragmentManager.beginTransaction().add(R.id.control_framelayout, this).commit()
            hangupCallback = {
                //呼叫时主动取消
                Toast.makeText(
                    this@VideoActivity,
                    "呼叫时长${DateFormatHelper.formatDate(it, "mm:ss")}",
                    Toast.LENGTH_LONG
                ).show()
                IMClient.getInstance().leaveRtcChannel(channelId, object : ICallback<Boolean>() {
                    override fun internalDone0(t: Boolean?, weException: WeException?) {
                        onBackPressed()
                    }
                })
            }
        }
    }

    private val videoAnswerFragment: VideoAnswerFragment by lazy {
        VideoAnswerFragment.newInstance(toClient, rtcType.code).apply {
            supportFragmentManager.beginTransaction().add(R.id.control_framelayout, this).commit()
            answerCallback = {
                //接听
                IMClient.getInstance().joinRtcChannel(channelId, object : ICallback<Boolean>() {
                    override fun internalDone0(t: Boolean?, weException: WeException?) {
                        videoControlFragment.show()
                        SoundPlayUtils.stopPlay()
                    }
                })
            }
            refusedCallback = {
                //拒绝
                IMClient.getInstance().rejectRtcCall(channelId, object : ICallback<Boolean>() {
                    override fun internalDone0(t: Boolean?, weException: WeException?) {
                        onBackPressed()
                    }
                })
            }
        }
    }

    private val videoControlFragment: VideoControlFragment by lazy {
        VideoControlFragment.newInstance(toClient, rtcType.code).apply {
            supportFragmentManager.beginTransaction().add(R.id.control_framelayout, this).commit()
            onVideoControl = videoControl
        }
    }

    private val videoControl = object : VideoControlFragment.OnVideoControl {
        override fun onHangUp(duration: Long) {
            //通话中挂断
            Toast.makeText(
                this@VideoActivity,
                "呼叫时长${DateFormatHelper.formatDate(duration, "mm:ss")}",
                Toast.LENGTH_LONG
            ).show()
            IMClient.getInstance().leaveRtcChannel(channelId, object : ICallback<Boolean>() {
                override fun internalDone0(t: Boolean?, weException: WeException?) {
                    onBackPressed()
                }
            })
        }

        override fun onMinimize() {
            //最小化
        }

        override fun onLoudSpeaker(micEnabled: Boolean) {
            //静音
            videoChatHelper?.setAudioEnabled(micEnabled)
        }

        override fun onHandsFree(speakerPhone: Boolean) {
            //免提
        }

        override fun onCameraChange() {
            //摄像头切换
            videoChatHelper?.switchCameraInternal { isSuccess, msg ->
                if (isSuccess) {
                    pip_video_view.setMirror(videoChatHelper?.isFront ?: false)
                } else {
                    Toast.makeText(this@VideoActivity, msg, Toast.LENGTH_LONG).show()
                }
            }
        }

    }

    private val rtcHandler = object : IMRTCHandler() {

        /**
         * 接收到RTC邀请
         */
//        override fun processCallEvent(conversation: IMConversation?, data: SubData?) {
//
//        }

        /**
         * 有client加入频道
         */
        override fun processJoinEvent(conversation: IMConversation?, data: RTCEvent?) {
            //对方同意加入频道 发送sdp offer
            if (data?.clientId == AppSharePre.getClientId())
                return
            videoChatHelper?.createLocalOffer { sdp, isSuccess ->
                if (sdp != null) {
                    Log.e(TAG, "发出offer")
                    IMClient.getInstance()
                        .sdpForward(channelId, sdp.description, "Offer",
                            object : ICallback<Boolean>() {
                                override fun internalDone0(t: Boolean?, weException: WeException?) {

                                }
                            })
                }
            }
            Log.e(TAG, "对方同意$data")
            videoControlFragment.show()
            SoundPlayUtils.stopPlay()
        }

        /**
         * 有client离开频道
         */
        override fun processLeaveEvent(conversation: IMConversation?, data: RTCEvent?) {
            //挂断
            Toast.makeText(this@VideoActivity, "对方离开房间", Toast.LENGTH_LONG).show()
            onBackPressed()
        }

        /**
         * 有Client拒绝加入频道
         */
        override fun processRejectEvent(conversation: IMConversation?, data: RTCEvent?) {
            Toast.makeText(this@VideoActivity, "对方拒绝接听", Toast.LENGTH_LONG).show()
            onBackPressed()
        }

        /**
         * client SDP 下发
         */
        override fun processSdpEvent(conversation: IMConversation?, data: RTCEvent?) {
            if (data == null)
                return
            Log.e(TAG, "收到${data.sdpType}")
            val sessionDescription = if (data.sdpType == "Answer") SessionDescription(
                SessionDescription.Type.ANSWER,
                data.sdpData
            ) else SessionDescription(SessionDescription.Type.OFFER, data.sdpData)
            videoChatHelper?.setRemoteDescription(sessionDescription) { sdp, isSuccess ->
                if (sdp != null) {
                    Log.e(TAG, "发出${sdp.type}")
                    IMClient.getInstance()
                        .sdpForward(channelId, sdp.description, "Answer",
                            object : ICallback<Boolean>() {
                                override fun internalDone0(t: Boolean?, weException: WeException?) {

                                }
                            })
                }
            }
        }

        /**
         * client Candidate 下发
         */
        override fun processCandidateEvent(conversation: IMConversation?, data: RTCEvent?) {
            if (data?.candidateData != null) {
                val jsonObj = JSON.parseObject(data.candidateData)
                val sdpMid = jsonObj.getString("sdpMid")
                val mLineIndex = jsonObj.getIntValue("sdpMLineIndex")
                val sdp = jsonObj.getString("candidate")
                val iceCandidate = IceCandidate(sdpMid, mLineIndex, sdp)
                videoChatHelper?.addIceCandidate(iceCandidate)
            }
        }
    }


    private var rootEglBase: EglBase? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_video)
        IMMessageManager.registerRTCMessageHandler(rtcHandler)
        channelId = intent.getLongExtra(CHANNEL_ID, 0L)
        rxPermission.request(
            Manifest.permission.MODIFY_AUDIO_SETTINGS,
            Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA
        ).subscribe {
            if (it) {
                initRTC()
            } else {
                onBackPressed()
            }
        }
        if (isCaller) {
            videoCallFragment.show()
        } else {
            videoAnswerFragment.show()
        }
        SoundPlayUtils.incomingTelegram()
    }

    override fun onStop() {
        SoundPlayUtils.stopPlay()
        super.onStop()
    }

    override fun onStart() {
        super.onStart()
//        videoChatHelper?.onStart()
    }

    override fun onDestroy() {
        disconnect()
        IMMessageManager.unregisterRTCMessageHandler(rtcHandler)
        super.onDestroy()
    }

    private fun initRTC() {
        if (rootEglBase == null) {
            rootEglBase = EglBase.create()
        }
        if (rtcType == Command.WeRtcType.RTC_TYPE_VIDEO) {
            pip_video_view.init(rootEglBase?.eglBaseContext, null)
            pip_video_view.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_BALANCED)
            pip_video_view.setZOrderMediaOverlay(true)
            pip_video_view.setEnableHardwareScaler(true)
            pip_video_view.setMirror(true)
            fullscreen_video_view.init(rootEglBase?.eglBaseContext, null)
            fullscreen_video_view.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL)
            fullscreen_video_view.setEnableHardwareScaler(true)
        }
        videoChatHelper?.initPeerAndLocalStream()
        videoChatHelper?.localProxyRenderer?.setTarget(fullscreen_video_view)
        videoChatHelper?.remoteProxyRenderer?.setTarget(pip_video_view)
        videoChatHelper?.cteatelPeer(AppSharePre.getClientId()) { candidate ->
            //转发ice
            val jsonObj = JSONObject()
            jsonObj.put("sdpMid", candidate?.sdpMid)
            jsonObj.put("sdpMLineIndex", candidate?.sdpMLineIndex)
            jsonObj.put("candidate", candidate?.sdp)
            IMClient.getInstance()
                .candidateForward(channelId, jsonObj.toString(), object : ICallback<Boolean>() {
                    override fun internalDone0(t: Boolean?, weException: WeException?) {
                    }
                })
        }

        if (isCaller) {
            IMClient.getInstance()
                .createAndCall(toClient, null, rtcType, conversationId, null, false, object :
                    ICallback<RTCChannel>() {
                    override fun internalDone0(t: RTCChannel?, weException: WeException?) {
                        if (weException!=null){
                            Toast.makeText(this@VideoActivity,weException.message,Toast.LENGTH_LONG).show()
                            onBackPressed()
                            return
                        }
                        channelId = t?.channelId ?: 0L
                        Log.e(TAG, "创建房间并加入$channelId")
                    }
                })
        }
        videoChatHelper?.onStart()
    }

    private fun disconnect() {
        SoundPlayUtils.handUpPlay()
        if (rootEglBase != null) {
            rootEglBase?.release()
            rootEglBase = null
        }
        videoChatHelper?.disconnect()
        fullscreen_video_view?.release()
        pip_video_view?.release()
    }
}